/*
 * By txdnet.cn tonydon
 * v1.7
 */
package txdnet.util;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * @author txdnet
 */
public class DataUtil {

    private DataUtil() {
    }
    private static Class clazz = DataUtil.class;
    
    /**
     * 检查对象数组是否为空
     * @param array
     * @return 
     */
    public static boolean isEmpty(Object[] array) {
        return (array == null || array.length == 0);
    }

    /**
     * 检查字符串是否为空
     *
     * @param value
     * @return boolean
     */
    public static boolean isEmpty(CharSequence value) {
        int strLen;
        if (value == null || (strLen = value.length()) == 0) {
            return true;
        }
        for (int i = 0; i < strLen; i++) {
            if ((Character.isWhitespace(value.charAt(i)) == false)) {
                return false;
            }
        }
        return true;
    }

    /**
     * 检查字符串是否为数字含小数
     *
     * @param value
     * @return boolean
     */
    public static boolean isNumeric(CharSequence value) {
        if (value == null) {
            return false;
        }
        char[] chars = value.toString().toCharArray();
        int length = chars.length;
        if (length < 1) {
            return false;
        }

        int i = 0;
        if (length > 1 && chars[0] == StaticMark.CHAR_LINE) {
            i = 1;
        }
        
        if(chars[length-1]==StaticMark.CHAR_DOT || !Character.isDigit(chars[i])){
            return false;
        }

        int n =0 ;
        for (; i < length; i++) {
            if(chars[i]==StaticMark.CHAR_DOT){
                n++;
            }
            if ( ( (!Character.isDigit(chars[i])) && chars[i]!=StaticMark.CHAR_DOT) || n>1) {
                return false;
            }
        }
        return true;
    }
    
    /**
     * 是否为整数型字符串
     * @param value
     * @return 
     */
    public static boolean isInteger(CharSequence value){
        if (value == null) {
            return false;
        }
        char[] chars = value.toString().toCharArray();
        int length = chars.length;
        if (length < 1) {
            return false;
        }

        int i = 0;
        if (length > 1 && chars[0] == StaticMark.CHAR_LINE) {
            i = 1;
        }
        
        for (; i < length; i++) {
            if (!Character.isDigit(chars[i])) {
                return false;
            }
        }
        return true;
    }

    /*分页显示输出页码链接函数
     strHref类似<a href=SubjectList-C701-{0}.htm >{1}</a>
     或<a href=ViewTopic!The{0}Page-C701.htm>{1}</a>
     step   输出页码长度
     pgcnt 页面总数/*, String PreMark_str, String NextMark_str)
     pgno 当前页码号
     */
    public static StringBuilder getPage(String tpl, String pgtag, int step, int ls, int row, int pgno) {
        //  int pgcnt = (row % ls ==0)?(row / ls) : ((int)(row / ls)+1);
        int pgcnt = DataUtil.getTotalPageNum(ls, row);//求总页数 
        StringBuilder sb = new StringBuilder();
        if ((pgno > pgcnt) || (pgno < 1) || (pgcnt == 1)) {
            return sb;
        }
        int p1 = (pgno == 1) ? 1 : (pgno - 1);
        int p2 = (pgno < pgcnt) ? (pgno + 1) : pgcnt;
        String fp = (pgno < 2) ? StaticMark.STR_EMPTY : tpl.replaceFirst(pgtag, "1").replace(pgtag, "第一页");
        String pre = (pgno <= 2) ? StaticMark.STR_EMPTY : tpl.replaceFirst(pgtag, Integer.toString(p1)).replace(pgtag, "上一页");
        String nex = (pgno > pgcnt - 2) ? StaticMark.STR_EMPTY : tpl.replaceFirst(pgtag, Integer.toString(p2)).replace(pgtag, "下一页");
        String ep = (pgno >= pgcnt) ? StaticMark.STR_EMPTY : tpl.replaceFirst(pgtag, Integer.toString(pgcnt)).replace(pgtag, "末页");
        sb.append(fp).append(pre).append("当前第").append(pgno).append("页");
        int n = pgno + 1;
        int k = pgno + step;
        if (k <= pgcnt) {
            for (int i = n; i <= k; i++) {
                sb.append(tpl.replace(pgtag, Integer.toString(i)));
            }
        } else {
            for (int j = n; j <= pgcnt; j++) {
                sb.append(tpl.replace(pgtag, Integer.toString(j)));
            }
        }
        /*
         * int k =(pgno/step)*step +1;
         //定位页码输出起始值K用于判断输出的页码组
         if( k+step-1 <= pgcnt )
         {
         for (int j=0 ;j<step; j++)
         {
         sb.append( tpl.replace(pgtag, Integer.toString(k) ) );
         k++;
         }
         }
         else
         {
         for(int i=k ; i<= pgcnt ; i++)
         {
         sb.append( tpl.replace(pgtag, Integer.toString(i) ) );
         }
         }
         *
         */
        return sb.append("共").append(pgcnt).append("页").append(nex).append(ep);
    }
    /*
     * @see 得到总页数
     */

    public static int getTotalPageNum(int ls, int row) {
        return (int) Math.ceil((double) row / ls);
    }
    /*
     @see 字符验证函数
     @param         被验证字符参数
     @regexp        用于验证的正则式
     @retstr 若param 为非法字符用此替换输出
     */

    public static String getValid(String val, String regexp, String retstr) {
        if (isEmpty(val)) {
            return retstr;
        }
        return val.matches(regexp) ? val : retstr;
    }

    /**
     * 字符验证函数，使用编译后的匹配模式快速判断是否符合模式要求，不符合则返回 retstr.
     *
     * @param val
     * @param p_regexp
     * @param retstr
     * @return
     */
    public static String getValid(String val, Pattern p_regexp, String retstr) {
        if (isEmpty(val)) {
            return retstr;
        }
        return p_regexp.matcher(val).matches() ? val : retstr;
    }

    /**
     * 检查,为空则返回一个定义值
     *
     * @param val
     * @param retstr
     * @return
     */
    public static String checkNull(String val, String retstr) {
        if (isEmpty(val)) {
            return retstr;
        } else {
            return val.trim();
        }
    }
    /*
     @see 从字串左方缩减字串
     @param str 原字符串
     @param length 缩减长度
     @return 缩减后字符

     public static String LString(String str, int length){
     StringBuilder sb = new StringBuilder(str);
     return sb.substring(length, sb.length());
     }
     */

    /**
     * 从字串右方缩减字串
     *
     * @param str 原字串
     * @param length 缩减长度
     * @return 缩减后字串
     *
     * public static String RString(String str, int length){ StringBuilder sb
     * =new StringBuilder(str); return sb.substring(0, (str.length() - length)
     * ); }
     */
    /**
     * @see 替换字符串取代String.replace() 提高性能
     * @param str 原字串
     * @param s1 被替换的字符串
     * @param s2 替换为的字符串
     * @return 返回替换后的结构
     */
    public static String replaceStr(String str, String s1, String s2) {
        if (str == null || s1 == null || s2 == null) {
            return null;
        }
        int i, j;
        if ((i = str.indexOf(s1, 0)) < 0) {
            return str;
        }
        if ((j = s1.length()) == 0) {
            return str;
        }
        int k;
        StringBuilder sb = new StringBuilder(str);
        int l = s2.length();
        for (; i >= 0; i = sb.indexOf(s1, k)) {
            sb.replace(i, i + j, s2);
            k = i + l;
        }
        return sb.toString();
    }

    /*
     *  @see 对文本截取定长字符串
     **/
    public static String cutText(String s, int size) {
        if (s == null) {
            return null;
        }
        String ss = s.trim();
        if (ss.length() == 0) {
            return null;
        }
        if (ss.length() < size) {
            return ss;
        } else {
            return ss.substring(0, size);
        }
    }

    /*
     * HTML过滤截取定长字符串
     * 不含HTML标签
     * 2012.2.4 -
     public static String cutXml(String s , int size){
     if(s==null){
     return null;
     }
     String ss = s.trim();
     if(ss.length()==0){
     return null;
     }
     ss = ss.replaceAll("(<[.[^<]]*>)|\n|\r|(\\s{2})","");
     if (ss.length()<size ){
     return ss;
     }else{
     return ss.substring(0,size);
     }
     }
     **/
    /**
     * 剔除xml成对标签
     *
     * @param s
     * @return
     */
    public static String clearXml(String s) {
        if (isEmpty(s)) {
            return StaticMark.STR_EMPTY;
        }
        return s.replaceAll(StaticMark.REGEX_CLEAR_XML, StaticMark.STR_EMPTY).trim();
    }
    
    /**
     * 过滤\r\n\t\f\b字符
     * @param value
     * @return 
     */
    public static String clearNonBlankChar(String value){
        if (isEmpty(value)) {
            return StaticMark.STR_EMPTY;
        }
        StringBuilder out = new StringBuilder();
        char currChar;
        int len = value.length();
        for(int i=0; i<len; i++){
            currChar = value.charAt(i);
            if(currChar == 10 || currChar == 13 || currChar==12 || currChar==9 || currChar == 8){
                continue;
            }
            out.append(currChar);
        }
        return out.toString();
    }

    /**
     * 剔除不可见字符
     *
     * @param value
     * @return String
     */
    public static String clearNonViewChar(String value) {
        if (isEmpty(value)) {
            return StaticMark.STR_EMPTY;
        }
        StringBuilder out = new StringBuilder();
        char current;
        int len = value.length();
        for (int i = 0; i < len; i++) {
            current = value.charAt(i);
            if ((current == 0x9) || (current == 0xA) || (current == 0xD)
                    || ((current >= 0x20) && (current <= 0xD7FF))
                    || ((current >= 0xE000) && (current <= 0xFFFD))
                    || ((current >= 0x10000) && (current <= 0x10FFFF))) {
                out.append(current);
            }
        }
        return out.toString();
    }
    /*@see 简单日期格式输出函数
     @param dateFormat_
     参数比如
     0 : yyyy-MM-dd HH:mm:ss
     1 : yyyyMMddHHmmssSSS
     可自行添加格式
     */

    public static String getDate(String DateFormatMark) {
        SimpleDateFormat sdf ;
        try {
            sdf = new SimpleDateFormat(DateFormatMark);
        } catch (RuntimeException ex) {
            Logger.error(clazz, ex.toString());
            return null;
        }
        return sdf.format(new Date());
    }

    /*
     * @see 日期字符转换Date格式
     */
    public static java.sql.Date parseDate(String datestr) {
        return DataUtil.parseDate(datestr, StaticMark.DTM_YYYY_MM_DD);
    }

    public static java.sql.Date parseDate(String datestr, String staticMark) {
        if (datestr == null) {
            return null;
        }
        SimpleDateFormat sdf = new SimpleDateFormat(staticMark);
        java.sql.Date date = null;
        try {
            date = new java.sql.Date(sdf.parse(datestr).getTime());
        } catch (ParseException ex) {
            Logger.error(clazz, ex.toString());
        }
        return date;
    }

    /*
     * @see 日期字符转换 1970 年 1 月 1 日 00:00:00 GMT 以来此 Date 对象表示的毫秒数
     */
    public static long parseMs(String datestr) {
        return DataUtil.parseMs(datestr, StaticMark.DTM_YYYY_MM_DD);
    }

    public static long parseMs(String datestr, String staticMark) {
        if (datestr == null) {
            return System.currentTimeMillis();
        }
        SimpleDateFormat sdf = new SimpleDateFormat(staticMark);
        long ms = 0l;
        try {
            ms = sdf.parse(datestr).getTime();
        } catch (ParseException ex) {
            Logger.error(clazz, ex.toString());
        }
        return ms;
    }

    public static java.sql.Date getDate() {
        return new java.sql.Date(System.currentTimeMillis());
    }

    /*
     * @see 返回sql.Timestamp类型时间戳
     */
    public static java.sql.Timestamp getTimestamp() {
        return new java.sql.Timestamp(System.currentTimeMillis());
    }

    public static java.sql.Timestamp getTimestamp(long ms) {
        return new java.sql.Timestamp(ms);
    }

    public static long getMs() {
        return System.currentTimeMillis();
    }
    /*
     @see 随机数产生函数
     @begin 开始于数值
     @limit 不可到达数值
     范围是 begin<=int f()<limit， 函数分布
     */

    public static int getRndInt(int begin, int limit) {
        return DataUtil.genRndInt(begin, limit);
    }
    /*@see 
     @begin 开始于数值
     @limit 不可到达数值
     范围是 begin<=int f()<limit， 均匀分布
     */

    public static int genRndInt(int begin, int limit) {
        return begin + (int) (Math.random() * (limit - begin));
    }

    /*
     * BigDecimal类型数值转换
     @param len 保留小数位数
     @param bigdecimal 需要进行转换的数值对象
     @param newScale 需要进行转的数值对象模式 BigDecimal.ROUND_HALF_UP
     @return 返回结果
     */
    public static BigDecimal parseRound(BigDecimal bigdecimal, int len, int newScale) {
        bigdecimal = bigdecimal.setScale(len, newScale);
        return bigdecimal;
    }

    /*
     * @see 四舍五入保留len长度的小数位.
     @param len 保留小数位数
     @param bigdecimal 需要进行四舍五入的数值对象
     @return 返回结果
     */
    public static BigDecimal parseRound(BigDecimal bigdecimal, int len) {
        return DataUtil.parseRound(bigdecimal, len, BigDecimal.ROUND_HALF_UP);
    }

    /*
     @see double值进行四舍五入保留2位小数.
     @param f 需要进行四舍五入的double对象
     @return 返回结果
     */
    public static double parseDouble(double d) {
        return DataUtil.parseRound(new BigDecimal(d), 2).doubleValue();
    }

    /*
     * @see 格式化显示小数数值 , 该转换为四舍五入模式
     @param d 双精度值
     @formatStr 格式化匹配模式串 如 #,##0.00
     */
    public static String formatDouble(double d, String formatStr) {
        DecimalFormat df = new DecimalFormat(formatStr);
        df.setRoundingMode(RoundingMode.HALF_UP);
        return df.format(d);
    }


    /*@see HTML FILTER
     */
    public static String parseTxt2Html(String str) {
        if (str == null) {
            return null;
        }
        if (str.trim().length() == 0) {
            return null;
        }
        StringBuilder sb = new StringBuilder(str.length());
        char ch;
        for (int i = 0; i < str.length(); i++) {
            ch = str.charAt(i);
            switch (ch) {
                case 38:
                    sb.append("&amp;");
                    break;
                case '“':
                    sb.append("&quot;");
                    break;
                case '”':
                    sb.append("&quot;");
                    break;
                case '‘':
                    sb.append("&#39;");
                    break;
                case '’':
                    sb.append("&#39;");
                    break;
                case 39:
                    sb.append("&#39;");
                    break;
                case '′':
                    sb.append("&#39;");
                    break;
                case '。':
                    sb.append(".");
                    break;
                case '，':
                    sb.append(",");
                    break;
                case '、':
                    sb.append(",");
                    break;
                case '；':
                    sb.append(";");
                    break;
                case '：':
                    sb.append(":");
                    break;
                case '？':
                    sb.append("?");
                    break;
                case '！':
                    sb.append("!");
                    break;
                case '〈':
                    sb.append("&lt;");
                    break;
                case '〉':
                    sb.append("&gt;");
                    break;
                case '（':
                    sb.append("(");
                    break;
                case '）':
                    sb.append(")");
                    break;
                case '【':
                    sb.append("[");
                    break;
                case '】':
                    sb.append("]");
                    break;
                case 60:
                    sb.append("&lt;");
                    break;
                case 62:
                    sb.append("&gt;");
                    break;
                case 34:
                    sb.append("&quot;");
                    break;
                case 13:
                    sb.append("");
                    break;
                case 10:
                    sb.append("<br/>");
                    break;
                default:
                    sb.append(ch);
            }
        }
        return sb.toString();

    }

// @see 不转换 & \n\r
    public static String filterCnDbStr(String str) {
        if (str == null) {
            return null;
        }
        if (str.trim().length() == 0) {
            return null;
        }
        StringBuilder sb = new StringBuilder(str.length());
        char ch;
        for (int i = 0; i < str.length(); i++) {
            ch = str.charAt(i);
            switch (ch) {
                case '“':
                    sb.append("&quot;");
                    break;
                case '”':
                    sb.append("&quot;");
                    break;
                case 34:
                    sb.append("&quot;");
                    break;
                case '‘':
                    sb.append("&#39;");
                    break;
                case '’':
                    sb.append("&#39;");
                    break;
                case 39:
                    sb.append("&#39;");
                    break;
                case '′':
                    sb.append("&#39;");
                    break;
                case '。':
                    sb.append(".");
                    break;
                case '，':
                    sb.append(",");
                    break;
                case '、':
                    sb.append(",");
                    break;
                case '；':
                    sb.append(";");
                    break;
                case '：':
                    sb.append(":");
                    break;
                case '？':
                    sb.append("?");
                    break;
                case '！':
                    sb.append("!");
                    break;
                case '〈':
                    sb.append("&lt;");
                    break;
                case '〉':
                    sb.append("&gt;");
                    break;
                case '（':
                    sb.append("(");
                    break;
                case '）':
                    sb.append(")");
                    break;
                case '【':
                    sb.append("[");
                    break;
                case '】':
                    sb.append("]");
                    break;
                default:
                    sb.append(ch);
            }
        }
        return sb.toString();
    }

    /* 
     * @see 格式化为XML字符串 替换特殊字符
     * @param s 需要处理的字符串
     * @return 处理后的字符串
     */
    public static String parseTxt2Xml(String s) {
        if (s == null || s.trim().length() == 0) {
            return null;
        }
        StringBuilder sb = new StringBuilder(s.length());
        char c;
        for (int i = 0; i < s.length(); i++) {
            c = s.charAt(i);
            switch (c) {
                case 9: // 'tab'
                    break;
                case 32: // '空格'
                    sb.append("&nbsp;");
                    break;

                case 39: // '\''
                    sb.append("&#39;");
                    break;

                case 34: // '"'
                    sb.append("&quot;");
                    break;

                case 60: // '<'
                    sb.append("&lt;");
                    break;

                case 62: // '>'
                    sb.append("&gt;");
                    break;

                case 38: // '&'
                    sb.append("&amp;");
                    break;

                default:
                    sb.append(c);
                    break;
            }
        }
        return sb.toString();
    }

    /**
     * 将Map<String,Object>转为GET请求?后参数查询串 最后带&符号 如果MAP为空或无元素侧返回null
     *
     * @param params
     * @return
     */
    public static String parseQueryString(Map<String, Object> params) {
        if (params == null || params.isEmpty()) {
            return StaticMark.STR_EMPTY;
        }
        StringBuilder sb = new StringBuilder();
        Map.Entry<?, ?> ent;
        for (Iterator<?> it = params.entrySet().iterator(); it.hasNext();) {
            ent = (Map.Entry<?, ?>) it.next();
            sb.append(ent.getKey())
                    .append(StaticMark.STR_EQUAL)
                    .append(ent.getValue()).append(StaticMark.STR_AND);
        }
        return sb.toString();
    }
}